<?php
/*******************************************************************************

    FinalsClub.org is a platform for students and faculty to collaborate
    and share their knowledge with the world.

    Copyright (C) 2009  Andrew Magliozzi

    This file is a part of FinalsClub.org.

    FinalsClub.org is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    To contact FinalsClub.org, send an email to info@finalsclub.org, or
    send mail to Finals Club, c/o Veritas Tutors, 1132 Massachusetts Avenue,
    Cambridge, MA 02138.

*******************************************************************************/

/**
 * notes actions.
 *
 * @package    FinalsClub
 * @subpackage notes
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 12474 2008-10-31 10:41:27Z fabien $
 */
class notesActions extends sfActions {

	public function executeIndex(sfWebRequest $request) {
		$this->group_id = $request->getParameter('group_id');
		$this->page = $request->getParameter('page', 1);
		$this->course_id = $request->getParameter('course_id');
		$this->lecture = $request->getParameter('lecture');
		$this->semester_id = $request->getParameter('semester_id', false);
		$this->forward404Unless(($this->course_id or $this->group_id),sprintf("Invalid Request"));
		$this->course = CoursePeer::retrieveByPk($this->course_id);
		
		if($this->group_id) {
			// This all needs to go to a component
			$groupCourses = GroupCoursePeer::retrieveByCourseId($this->course_id);
			$groups = array();
			foreach ($groupCourses as $groupCourse) {
				$groups[] = $groupCourse->getGroup();
			}
			$this->groups = $groups;
			// end related groups	
			$group_member = GroupMemberPeer::retrieveByUserIdAndGroupId($this->getUser()->getId(),$this->group_id);
			if(!$this->getUser()->isAdmin()) {
				$this->forward404Unless($group_member);				
			}
			$this->group = GroupPeer::retrieveByPk($this->group_id);			

			if($this->course_id) {
				$this->notes_pager = NotePeer::retrieveByCourseIdAndGroupIdPager($this->course_id, $this->group_id, $this->page, 10, $this->semester_id, $this->lecture);	
				$this->setTemplate('group_courseindex');			
			} else {
				
				//ajax request for group home
				if($request->getParameter('isAjax'))
				{
					$this->setTemplate('grouphome');
				}
				else
				{
					$this->setTemplate('groupindex');
				}
							
			}
			
		} else {
			if($this->getUser()->isAdmin()) {
				$this->notes_pager = NotePeer::retrieveAllByCourseIdPager($this->course_id, $this->page, 10);
			} else {
				$this->notes_pager = NotePeer::retrieveByCourseIdPager($this->course_id, $this->getUser()->getId(), $this->page, 10);				
			}
		}		
	}

	/**
	 * deleterevision action. Deletes a revision of a note object, but never the note table row itself. To delete a note and it's versions, call Note::delete
	 * it is overloaded to also delete revisions.
	 * @param sfWebRequest $request symfony request object.
	 * @param intval(string) $_GET['id'] The note ID number.
	 * @param intval(string) $_POST['version'] The revision number.
	 * @param intval(string) $_POST['version_comment'] The revision comment.
	 * @return redirect Redirects to note/show. Injections error or success information.
	 */
	public function executeDeleterevision(sfWebRequest $request) {
		$this->forward404Unless($request->getParameter('id'));
		$note_id = $request->getParameter('id');

		$data = $request->getPostParameters();

		if(empty($data['version'])) {
			$this->getUser()->setFlash('error', 'There was an error trying to delete that revision.');
			$this->redirect('notes/show?id=' . $note_id);
		}

		$version = intval($data['version']);
		$comment = isset($data['version_comment']) ? $data['version_comment'] : '';
		$user_id = $this->getUser()->getId();

		$note = NotePeer::retrieveByPk($note_id);

		// Do not perform this action if the version is terminal (i.e. only one non-deleted version exists)
		if($note->isTerminalVersion()) {
			$this->getUser()->setFlash('error','You can not delete this version; it is the only publishable revision.');
			$this->redirect('notes/show?id=' . $note_id);
		}

		$result = $note->versionDelete($version,$user_id,$comment);

		if(!$result)
			$this->getUser()->setFlash('error', 'There was an error trying to delete that revision.');

		$this->getUser()->setFlash('success','Revision deleted.');

		$this->redirect('notes/show?id=' . $note_id);
	}

	/**
	 * Reverts to a previous revision. Specifically, takes the contents of an older revision and creates a new revision, making it the most recent.
	 * @param sfWebRequest $request symfony request object.
	 * @param intval(string) $_GET['id'] The note ID number.
	 * @param intval(string) $_POST['version'] The revision number.
	 * @param intval(string) $_POST['version_comment'] The revision comment.
	 * @return redirect Redirects to note/show. Injections error or success information.
	 * @author CROSCON
	 */
	public function executeRevert(sfWebRequest $request) {
		$this->forward404Unless($request->getParameter('id'));
		$note_id = $request->getParameter('id');

		$data = $request->getPostParameters();
		if(empty($data['version'])) {
			$this->getUser()->setFlash('error','Invalid version');
			$this->redirect('notes/show?id=' . $note_id);
		}

		$version = intval($data['version']);
		$comment = isset($data['version_comment']) ? $data['version_comment'] : '';
		$user_id = $this->getUser()->getId();

		$note = NotePeer::retrieveByPk($note_id);
		$note->toVersion($version);
		$note->setVersionCreatedBy($user_id);
		$note->setVersionComment($comment);

		if($note->save()===false) {
			$this->getUser()->setFlash('error','There was an error trying to revert the note.');
		} else {
			$this->getUser()->setFlash('success','Note reverted.');
		}

		$this->redirect('notes/show?id=' . $note_id);
	}

	/**
	 * Perform a comparison operation of 2+ note versions via an HTML diff.
	 * @param sfWebRequest $request symfony request object.
	 * @param intval(string) $_GET['id'] The note ID.
	 * @param array $_POST['versions'] An array of version ID numbers to compare.
	 * @author CROSCON
	 */
	public function executeCompare(sfWebRequest $request) {

		$this->forward404Unless($note = NotePeer::retrieveByPk($request->getParameter('id')), sprintf('Those notes do not exist for id (%s).', $request->getParameter('id')));
		$this->root_note = $note;

		$this->subject = $note->getCourse()->getSubject();
		$this->subject_name = $note->getCourse()->getSubject()->getName();
		$this->course_name = $note->getCourse()->getName();

		$data = $request->getPostParameters();
		$this->forward404Unless(isset($data['versions']) && count($data['versions']));

		$data = $data['versions'];

		$versions = $note->getAllVersionsSafe();

		$notes = array();

		foreach($versions as $note) {
			if(in_array($note->getVersion(),$data)) {
				$n = $note->toArray();
				$n['VersionCreatedBy'] = $note->getVersionCreatedBy();
				$n['VersionCreatedAt'] = $note->getVersionCreatedAt();
				$n['VersionComment'] = $note->getVersionComment();

				$n['user'] = UserPeer::retrieveByPk($n['VersionCreatedBy']);

				$notes[] = $n;
			}
		}

		if(count($notes)!=2) {
			$this->getUser()->setFlash('error','Please select two versions to compare');
			$this->redirect('notes/history?id=' . $root_note->getId());
		}

		$this->note_history = $notes;

		$current_version = end($versions);
		$this->current_version = $current_version->toArray();
	}

	/**
	 * Shows a note.
	 * @param sfWebRequest $request symfony request object
	 * @param intval(string) $_GET['id'] The note ID.
	 * @param intval(string) $_GET['version'] Optional parameter specifying the note's version number. Defaults to most current.
	 * @author CROSCON
	 */
        public function executeShow(sfWebRequest $request) {
		$this->forward404Unless($note = NotePeer::retrieveByPk($request->getParameter('id')), sprintf('Those notes do not exist for id (%s).', $request->getParameter('id')));
		$this->forward404Unless(EntitlementPeer::isEntitled($note->getId(),$this->getUser()->getId(), EntitlementPeer::NOTE_TYPE ,EntitlementPeer::READ_PERMISSION), sprintf("You are not permitted to access this resource"));
		$version_id = $request->getParameter('version');
		if($version_id) {
			$this->version_id = $version_id;
			$note->toVersion($version_id);
			$this->forward404Unless(!$note->getDeleted(),sprintf("Version %d of this document was been deleted and can not be viewed.",$version_id));
		}

		$this->terminal_version = $note->isTerminalVersion();
		$this->note = $note;

		$this->show_annotations = ($this->getUser()->isAuthenticated());
		if($this->show_annotations) {
			$this->getResponse()->addJavascript('/js/annotate.js', 'last');
			$this->getResponse()->addJavascript('/fckeditor/fckeditor.js', 'last');
			$annotate_api = new AnnotateApi();
			$annotate_base_url = $annotate_api->getBaseURL();

			$owner_id = $this->note->getUserId();
			$user_id = $this->getUser()->getId();
			$this->annotate_isowner = ($owner_id == $user_id);

			$owner = UserPeer::retrieveById($owner_id);
			$this->annotate_owner = $annotate_api->encodeEmail($owner->getEmail());
			$this->annotate_owner_sig = $owner->getUsername();

			$user = UserPeer::retrieveById($user_id);
			$this->annotate_user_sig = $user->getUsername();

			$this->annotate_title = "FinalsClub.com Notes - ".ucwords($note->getType())." ".$note->getNumber().": ".$note->getTopic();
			$this->getResponse()->addJavascript($annotate_base_url . '/js/web_annotate.js', 'last'); // this is part of the a.nnotate distribution
		}
			
        }

	/**
	 * Shows a note's version history.
	 * @param sfWebRequest $request symfony request object.
	 * @param intval(string) $_GET['id'] The note ID number.
	 * @author CROSCON
	 */
	public function executeHistory(sfWebRequest $request) {
		$this->forward404Unless($note = NotePeer::retrieveByPk($request->getParameter('id')), sprintf('Those notes do not exist for id (%s).', $request->getParameter('id')));

		//$note = NotePeer::retrieveByPk($request->getParameter('id'));

		$note = new Note();
		$note->setId($request->getParameter('id'));
		$this->forward404Unless($data = $note->getAllVersionsSafe());

		$users = array();
		foreach($data as $note) {
			$user_id = $note->getVersionCreatedBy();
			if(!empty($user_id)) {
				$u = UserPeer::retrieveByPk($user_id);
				$users[$user_id] = $u->toArray();
			}
		}

		$this->users = $users;
		$this->note_history = $data;
		$this->note = $note;
	}

	public function executeNew(sfWebRequest $request) {
		$this->form = new NoteForm();
		$this->course = CoursePeer::retrieveById($request->getParameter('course_id'));
		// $oFCKeditor = Utils::getFCKEditor('note[text]');
		$oFCKeditor = FCKDrawUtil::getFCKDrawEditor('note[text]');
		$this->oFCKeditor = $oFCKeditor;
		$this->setTemplate('edit');
		$this->isNew = true;
		
		
		$this->subjects = SubjectPeer::retrieveAll();
	}

	public function executeCreate(sfWebRequest $request) {
		$this->forward404Unless($request->isMethod('post'));

		$this->form = new NoteForm();
		$note = $request->getParameter('note');
		$note['user_id'] = $this->getUser()->getId();
		$note['group_id'] = $request->getParameter('group_id');
		$request->setParameter('note', $note);
		$this->processForm($request, $this->form);
	}

	public function executeEdit(sfWebRequest $request) {
		$this->forward404Unless($note = NotePeer::retrieveByPk($request->getParameter('id')), sprintf('Those notes do not exist for id (%s).', $request->getParameter('id')));
		$this->forward404Unless(EntitlementPeer::isEntitled($note->getId(),$this->getUser()->getId(), EntitlementPeer::NOTE_TYPE, EntitlementPeer::WRITE_PERMISSION, "You are not allowed to edit these resources"));
		
		// make sure the user is allowed to edit these notes
        if($this->getUser()->getId() == $note->getUserId() || $this->getUser()->isAdmin() 
        	|| $this->getUser()->isGroupContributor($note->getGroupId()) 
        	|| $this->getUser()->isGroupAdmin($note->getGroupId())) {
			$this->course = $note->getCourse();
			$this->form = new NoteForm($note);
			// $oFCKeditor = Utils::getFCKEditor('note[text]');
			$oFCKeditor = FCKDrawUtil::getFCKDrawEditor('note[text]');
			$oFCKeditor->Value = $note->getText();
			$this->oFCKeditor = $oFCKeditor;
			$this->note = $note;

		} else {
			$this->getUser()->setFlash('error', 'You do not have permssion to edit these notes.');
			$request->setParameter('course_id', $note->getCourseId());
			$this->redirect($request->getReferer());
		}
		
		$this->subjects = SubjectPeer::retrieveAll();
		
	}

	public function executeUpdate(sfWebRequest $request) {
                $this->forward404Unless($request->isMethod('post') || $request->isMethod('put'));
                $this->forward404Unless($note = NotePeer::retrieveByPk($request->getParameter('id')), sprintf('Those notes do not exist for id (%s).', $request->getParameter('id')));
                // make sure the user is allowed to edit these notes
                $noteRequest = $request->getParameter('note');

                /* If the the old visibility does not equal the form visbility, and this user is neither the creator of this note
                 * nor the administrator of this group, forward 404 because they are not authorized to make this change.
                 * Just to note, the only way this boolean would evaluate to true and forward 404 should be if an artificial
                 * post is somehow sent over, which indicates a malicious intent and hence should be replied to in the most
                 * impersonal way possible (hence the 404)
                 */

                if(!$this->getUser()->isAdmin() && $this->getUser()->getId() != $note->getUserId()
                        && !$this->getUser()->isGroupContributor($note->getGroupId())
                        && !$this->getUser()->isGroupAdmin($note->getGroupId())) {
                        $this->forward404Unless(false, "You have attempted to make an unauthorized action");
                }
        if($this->getUser()->getId() == $note->getUserId() || $this->getUser()->isAdmin() 
        	|| $this->getUser()->isGroupContributor($note->getGroupId()) 
        	|| $this->getUser()->isGroupAdmin($note->getGroupId())) {
			$this->form = new NoteForm($note);
			$this->processForm($request, $this->form);
			$this->setTemplate('show');
		} 
		else {
			$this->getUser()->setFlash('error', 'You do not have permssion to update these notes.');
			$request->setParameter('course_id', $note->getCourseId());
			$this->forward('notes', 'index');
		}
	}

	public function executeDelete(sfWebRequest $request) {
		$request->checkCSRFProtection();

		$this->forward404Unless($note = NotePeer::retrieveByPk($request->getParameter('id')), sprintf('Object note does not exist (%s).', $request->getParameter('id')));
			// make sure that the user has permissions to delete the notes
		if($this->getUser()->getId() == $note->getUserId()) {
			$this->getUser()->setFlash('success', 'Your notes have been successfully deleted.');
			$note->delete();
		}

		$this->redirect('notes/index?course_id='.$note->getCourseId());
	}
	
	public function executeList(sfWebRequest $request) {
		
		$this->group_id = $request->getParameter('group_id', 1);
		$this->semester_id = $request->getParameter('semester_id',false);
		$this->group = GroupPeer::retrieveByPk($this->group_id);
		// retrieve all notes for a given group
		if($this->semester){
			$this->notes_pager = NotePeer::retrieveByGroupIdAndSemesterIdPager($this->group_id, $request->getParameter('page', 1). 10 , $this->semester_id);
		}else{
			$this->notes_pager = NotePeer::retrieveByGroupIdPager($this->group_id, $request->getParameter('page', 1). 10 );
			
		}
	}
	public function executeBatch(sfWebRequest $request){
		$this->group_id = $request->getParameter('group_id');
		$this->course_id = $request->getParameter('course_id');
		$this->state = $request->getParameter('state');
		$group_member = GroupMemberPeer::retrieveByUserIdAndGroupId($this->getUser()->getId(), $this->group_id);
		$this->activated = ($group_member->getRole() == 3 ? true : false);
		if ($this->activated){
			$notes = NotePeer::retrieveByCourseIdAndGroupId($this->course_id, $this->group_id);
			foreach ($notes as $note){ /* Iterate through notes, and change visibility on each */
				$note->setVisibility($this->state);
				$note->save();
			}

		}
	}
	
	protected function processForm(sfWebRequest $request, sfForm $form) {
		$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
		if ($form->isValid()) {
			$status = $form->getObject()->isNew() ? 'created' : 'updated';
			$this->getUser()->setFlash('success', 'Your notes have been successfully '.$status);
			$note = $form->updateObject(); 
			$note->setUserId($this->getUser()->getId());	// prevent the user from maliciously changing the creator 
			
			/*
			$config = HTMLPurifier_Config::createDefault();
			$config->set('HTML','Allowed','p,b,a[href][target],i,u,br,ul,ol,li');
			$purifier = new HTMLPurifier($config);
            $clean_html = $purifier->purify($form->getValue('text'));
			$note->setText($clean_html);
			*/
			
			if($status == 'updated') {
				$comment = $request->getParameter('version_notes') ? $request->getParameter('version_notes') : 'No reason given.';
				$note->setVersionComment($comment);
			} else {
				$note->setVersionComment('Original version.');
			}

			$note->save();
			
			// $form->getObject()->isNew() && 
//			if ($this->getUser()->isLoggedInFacebookUser() && FacebookUtility::has_granted_permission('create_note')) {
//				FacebookUtility::publish_note($note->getTopic(), $note->getText(), $this->getUser()->isFacebookUser());
//			}

			$publishToFacebook = ($request->getParameter('publish_to_facebook', false) == "publish" );
			if ($this->getUser()->isLoggedInFacebookUser() && $publishToFacebook) {
				// TODO (Chris) get copy
				$course = CoursePeer::retrieveById($note->getCourseId());
				$content = " " . $status . " a Finals Club note in this course: " . $course->getName();
				FacebookUtility::register_feed_form_js($content);
			}			

			// if a task was specified, update the task with the id of the new resource
			$task_id = $request->getParameter('task_id');
			if($task_id && $task = TaskPeer::retrieveById($task_id)) {
				$task->setResourceId($note->getId());
				$task->save();
			}

			$this->redirect('notes/show?id='.$note->getId());
		}
	}
	

	public function executeProfilelist(sfWebRequest $request){
		$user_id = $request->getParameter('id');	
		
		return $this->renderComponent('notes','profileList', array('user_id'=>$user_id));
	
	}
	
	public function executeProfilecourse(sfWebRequest $request){
			$user_id = $request->getParameter('id');	
		
			return $this->renderComponent('notes','profileCourse', array('user_id'=>$user_id));
	
	}
	
	public function executeProfiledetail(sfWebRequest $request){
			$user_id = $request->getParameter('id');	
		
			return $this->renderComponent('notes','profileDetail', array('user_id'=>$user_id));
	
	}
	
}
